﻿#include"Sort.h"

//打印
void PrintArray(int* a, int n)
{
	for(int i=0;i<n;i++)
		{
		printf("%d ", a[i]);
		}
	printf("\n");
}


//插入排序 - 稳定
// 时间复杂度：O(n²)
// 空间复杂度：O(1)
void InsertSort(int* a, int n)
{
	for (int i = 0;i<n-1; i++)
	{
		//[0,end]有序，把end+1位置的值插入进去
		int end = i;
		int tmp = a[end + 1];
		while (end >= 0)
		{
			if (a[end] > tmp)
			{
				a[end + 1] = a[end];
				end--;
			}
			else
			{
				break;
			}
		}
		a[end + 1] = tmp;
	}
}

//希尔排序 - 不稳定
// 时间复杂度：O(N^1.3)
// 空间复杂度：O(1)
void ShellSort(int* a, int n)
{
	/*int gap = 3;
	for (int i = 0; i < gap; i++)
	{
		for (int j = i; j < n - gap; j += gap)
		{
			int end = j;
			int tmp = a[end + gap];
			while (end >= 0)
			{
				if (tmp < a[end])
				{
					a[end + gap] = a[end];
					end -= gap;
				}
				else
				{
					break;
				}
				a[end + gap] = tmp;
			}
		}
	}*/

	int gap = n;//gap==1时，等于插入排序
	while (gap > 1)
	{
		gap = gap / 3 + 1;

		for (int i = 0; i < n - gap; i++)
		{
			int end = i;
			int tmp = a[end + gap];
			while (end >= 0)
			{
				if (tmp < a[end])
				{
					a[end + gap] = a[end];
					end -= gap;
				}
				else
				{
					break;
				}
				a[end + gap] = tmp;
			}
		}
	}
}


//堆排序 - 不稳定
// 时间复杂度：O(N*logN)
// 空间复杂度：O(1)
void Swap(int* p1, int* p2)
{
	int tmp = *p1;
	*p1 = *p2;
	*p2 = tmp;
}
void AdjustDown(int *a, int n, int parent)
{
	int child = parent * 2 + 1;
	while (child < n)
	{
		if (child + 1 < n && a[child + 1] > a[child])
		{
			child++;
		}
		if (a[child] > a[parent])
		{
			Swap(&a[child], &a[parent]);
			parent = child;
			child = parent * 2 + 1;
		}
		else
		{
			break;
		}
	}

}
void HeapSort(int* a, int n)
{
	//向下调整建堆
	for (int i = (n - 1 - 1) / 2; i >= n; i--)
	{
		AdjustDown(a, n, i);
	}
	int end = n - 1;
	while (end > 0)
	{
		Swap(&a[0], &a[end]);
		AdjustDown(a, end, 0);
		end--;
	}
}


//冒泡排序 - 稳定
// 时间复杂度：O(N²)
// 空间复杂度：O(1)
void BubbleSort(int* a, int n)
{
	for (int i = 0; i < n ; i++)
	{
		int flag = 0;
		for (int j = 0; j < n - 1 - i; j++)
		{
			if (a[i - 1] > a[j])
			{
				Swap(&a[j - 1], &a[j]);
				flag = 1;
			}
		}
		if (flag == 0)
		{
			break;
		}
	}
}


//选择排序 - 不稳定
// 时间复杂度：O(N²)
// 空间复杂度：O(1)
void SelectSort(int* a, int n)
{
	int begin = 0, end = n - 1;
	while (begin < end)
	{
		int maxi = begin, mini = begin;
		for (int i = begin + 1; i <= end; i++)
		{
			if (a[i] > a[maxi])
			{
				maxi = i;
			}
			if (a[i] < a[mini])
			{
				mini = i;
			}
		}
		Swap(&a[begin], &a[mini]);
		if (begin == maxi)
		{
			maxi = mini;
		}
		Swap(&a[end], &a[maxi]);
		begin++;
		end--;
	}
}


//快速排序 - 不稳定
// 时间复杂度：O(N*logN)
// 空间复杂度：O(logN)
//避免有序情况下效率退化
//1.随机选key
//2.三数取中
int GetMidi(int *a,int left,int right)
{
	int midi = (left + right) / 2;
	if (a[left] < a[midi])
	{
		if (a[midi] < a[right])
		{
			return midi;
		}
		else if (a[left] < a[right])
		{
			return right;
		}
		else
		{
			return left;
		}
	}
	else // a[left]>a[midi]
	{
		if (a[midi] > a[right])
		{
			return midi;
		}
		else if (a[right] > a[left])
		{
			return left;
		}
		else
		{
			return right;
		}
	}
}
//hoare
int  PartSort1(int* a, int left, int right)
{
	//三数取中
	int midi = GetMidi(a, left, right);
	Swap(&a[left], &a[midi]);
	int keyi = left;
	int begin = left, end = right;
	while (begin < end)
	{
		//右边找小
		while (begin < end && a[end] >= a[keyi])
		{
			--end;
		}
		//左边找大
		while (begin < end && a[begin] <= a[keyi])
		{
			++begin;
		}

		Swap(&a[begin], &a[end]);
	}
	Swap(&a[keyi], &a[begin]);
	return begin;
}
//前后指针
int PartSort2(int* a, int left, int right)
{
	//三数取中
	int midi = GetMidi(a, left, right);
	Swap(&a[left], &a[midi]);
	int keyi = left;

	int prev = left;
	int cur = prev + 1;
	while (cur<=right)
	{
		if (a[cur] < a[keyi]&&++prev!=cur)
		{
			Swap(&a[prev], &a[cur]);
		}
		cur++;
	}
	Swap(&a[prev], &a[keyi]);
	return prev;
}
void QuickSort(int* a, int left,int right)
{
	if (left >= right)
	{
		return;
	}
	//小区间优化,不再递归分割排序，减少递归次数
	if ((right - left + 1) < 10)
	{
		InsertSort(a + left,right-left+1 );
	}
	else
	{
		int keyi = PartSort1(a,left,right);
		//[left,key-1]  keyi  [keyi+1,right]
		QuickSort(a, left, keyi - 1);
		QuickSort(a, keyi + 1, right);
	}
}
//非递归快排
#include"Stack.h"
void QuickSortNonR(int* a, int left, int right)
{
	ST st;
	STInit(&st);
	STPush(&st, right);
	STPush(&st, left);

	while (!STEmpty(&st))
	{
		int begin = STTop(&st);
		STPop(&st);
		int end = STTop(&st);
		STPop(&st);

		int keyi = PartSort2(a, begin, end);
		// [begin,keyi-1] keyi [keyi+1,end]
		if (keyi + 1 < end)
		{
			STPush(&st, end);
			STPush(&st, keyi+1);
		}
		if (begin<keyi-1)
		{
			STPush(&st, keyi-1);
			STPush(&st, begin);
		}
	}
	STDestroy(&st);
}


//归并排序 - 稳定
// 时间复杂度：O(N*logN)
// 空间复杂度：O(N)
void _MergeSort(int* a, int *tmp,int begin ,int end)
{
	if (begin == end)
	{
		return;
	}
	int mid = (begin + end) / 2;
	// 如果[begin ,mid-1] [mid,end]有序，即可进行归并
	_MergeSort(a, tmp, begin, mid);
	_MergeSort(a, tmp, mid+1, end);

	//归并
	int begin1 = begin, end1 = mid;
	int begin2 = mid+1, end2 = end;
	int i = begin;
	while (begin1<=end1&&begin2<=end2)
	{
		if (a[begin1] <= a[begin2])
		{
			tmp[i++] = a[begin1++];
		}
		else
		{
			tmp[i++] = a[begin2++];
		}
	}
	while (begin1 <= end1)
	{
		tmp[i++] = a[begin1++];
	}
	while(begin2 <= end2)
	{
		tmp[i++] = a[begin2++];
	}
	memcpy(a+begin, tmp+begin, (end - begin + 1) * sizeof(int));
}
void MergeSort(int* a, int n)
{
	int* tmp = (int*)malloc(sizeof(int) * n);
	if (tmp == NULL)
	{
		perror("malloc fail");
		return;
	}
	_MergeSort(a, tmp, 0, n - 1);

	free(tmp);
	tmp = NULL;
}
//非递归归并排序
void MergeSortNonR(int* a, int n)
{
	int* tmp = (int*)malloc(sizeof(int) * n);
	if (tmp == NULL)
	{
		perror("malloc fail");
		return;
	}
	// gap每组归并数据的个数
	int gap = 1;	
	while (gap<n)
	{
		for (int i = 0; i < n; i += 2 * gap)
		{
			// [begin1,end1] [begin2,end2]
			int begin1 = i, end1 = i + gap - 1;
			int begin2 = i + gap, end2 = i + 2 * gap - 1;
			//第二组越界不存在，这一组不需要归并
			if (begin2 >= n)
			{
				break;
			}
			// 第二组begin2没越界，end2越界了，需要修正一下,继续归并
			if (end2 >= n)
			{
				end2 = n - 1;
			}
			int j = i;
			while (begin1 <= end1 && begin2 <= end2)
			{
				if (a[begin1] < a[begin2])
				{
					tmp[j++] = a[begin1++];
				}
				else
				{
					tmp[j++] = a[begin2++];
				}
			}
			while (begin1 <= end1)
			{
				tmp[j++] = a[begin1++];
			}
			while (begin2 <= end2)
			{
				tmp[j++] = a[begin2++];
			}
			memcpy(a + i, tmp + i, sizeof(int) * (end2 - i + 1));
		}
		gap *= 2;
	}

	free(tmp);
	tmp = NULL;
}

//计数排序 - 只适合整数/范围集中的
// 时间复杂度：O(N+range)
// 空间复杂度；O(range)
void CountSort(int* a, int n)
{
	int min = a[0], max = a[0];
	for (int i = 1; i < n; i++)
	{
		if (a[i] < min)
		{
			min = a[i];
		}
		if (a[i] > max)
		{
			max = a[i];
		}
	}
		int range = max - min + 1;
		int* count = (int*)calloc(range, sizeof(int));
		if (count == NULL)
		{
			perror("calloc fail");
			return;
		}

		//统计次数
		for (int i = 0; i < n; i++)
		{
			count[a[i] - min]++;
		}

		//排序
		int j = 0;
		for (int i = 0; i < range; i++)
		{
			while (count[i]--)
			{
				a[j++] = i + min;
			}
		}
		free(count);
	
}
